package com.baor.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baor.dao.*;
import com.baor.domain.*;
import com.baor.service.ExceptionManagerService;
import com.baor.util.R;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

//设备管理
@Service
@Transactional
@Slf4j
public class ExceptionManagerServiceImpl implements ExceptionManagerService {
    @Autowired
    private EquipmentDao equipmentDao;

    @Autowired
    private Equipment_installDao equipment_installDao;

    @Autowired
    private Equipment_cleanDao equipment_cleanDao;
    @Autowired
    private Equipment_logDao equipment_logDao;
    @Autowired
    private OrganizationDao organizationDdao;

    @Override
    public R getCode(Map<String, Object> params) {
        Page page = new Page();
        page.setCurrent((Integer) params.get("pageIndex"));
        page.setSize((Integer) params.get("pageSize"));
        MPJLambdaWrapper<Equipment> wrapper = new MPJLambdaWrapper<>(Equipment.class)
                .select(Equipment::getId,
                        Equipment::getCode,
                        Equipment::getAddress);
        Page<EquipmentNameVO> pageList = equipmentDao.selectJoinPage(page, EquipmentNameVO.class, wrapper);
        Map map = new HashMap();
        map.put("totalSize", pageList.getTotal());
        map.put("List", pageList.getRecords());
        return R.ok(map) ;
    }

    @Override
    public R getList(Map<String, Object> params) {
        Page<Equipment> page = new Page<>();
        page.setCurrent((Integer) params.get("pageIndex"));
        page.setSize((Integer) params.get("pageSize"));

        // 第一步：查询设备基本信息
        MPJLambdaWrapper<Equipment> wrapper = new MPJLambdaWrapper<>(Equipment.class)
                .selectAll(Equipment.class)
                .eq(Equipment::getIsDeleted, 0)
                .orderByDesc(Equipment::getId);

        // 条件过滤
        buildQueryConditions(wrapper, params);

        // 查询设备数据
        Page<Equipment> equipmentPage = equipmentDao.selectPage(page, wrapper);
        List<Equipment> equipmentList = equipmentPage.getRecords();
        // 第二步：获取清理人员信息并组装VO
        List<ExceptionManagerVO> voList = getEquipmentWithCleanList(equipmentList);
        Map<String, Object> map = new HashMap<>();
        map.put("totalSize", equipmentPage.getTotal());
        map.put("list", voList);
        return R.ok(map);
    }

    /**
     * 获取设备列表并添加清理人员信息
     */
    private List<ExceptionManagerVO> getEquipmentWithCleanList(List<Equipment> equipmentList) {
        if (equipmentList == null || equipmentList.isEmpty()) {
            return new ArrayList<>();
        }

        // 获取所有设备ID
        List<Integer> equipmentIds = equipmentList.stream()
                .map(Equipment::getId)
                .collect(Collectors.toList());

        // 批量查询设备与清理人员的关联关系
        List<Equipment_clean> cleanRelations = equipment_cleanDao.selectByEquipmentIds(equipmentIds);

        // 按设备ID分组清理人员ID
        Map<Integer, List<Long>> equipmentCleanMap = cleanRelations.stream()
                .filter(relation -> relation.getCleanId() != null)
                .collect(Collectors.groupingBy(
                        Equipment_clean::getEquipmentId,
                        Collectors.mapping(relation -> Long.valueOf(relation.getCleanId()), Collectors.toList())
                ));

        // 转换为VO
        return equipmentList.stream().map(equipment -> {
            ExceptionManagerVO vo = new ExceptionManagerVO();
            // 拷贝设备属性
            copyEquipmentProperties(equipment, vo);

            // 设置清理人员列表
            List<Long> cleanList = equipmentCleanMap.get(equipment.getId());
            vo.setCleanList(cleanList != null ? cleanList : new ArrayList<>());

            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 拷贝设备属性到VO
     */
    private void copyEquipmentProperties(Equipment equipment, ExceptionManagerVO vo) {
        vo.setId(equipment.getId());
        vo.setSalesName(equipment.getSalesName());
        vo.setSalesPhone(equipment.getSalesPhone());
        vo.setEquipmentSn(equipment.getEquipmentSn());
        vo.setCode(equipment.getCode());
        vo.setPrice(String.valueOf(equipment.getPrice()));
        vo.setThreshold(String.valueOf(equipment.getThreshold()));
        vo.setLatitude(equipment.getLatitude());
        vo.setLongitude(equipment.getLongitude());
        vo.setName(equipment.getName());
        vo.setVersionNumber(equipment.getVersionNumber());
        vo.setAddress(equipment.getAddress());
        vo.setTotalWeight(equipment.getTotalWeight());
        vo.setNowWeight(equipment.getNowWeight());
        vo.setStatus(equipment.getStatus());
        vo.setStorageStatus(equipment.getStorageStatus());
        vo.setIsStatus(equipment.getIsStatus());
        vo.setLastUseTime(equipment.getLastUseTime());
        vo.setRemarks(equipment.getRemarks());
    }
    /**
     * 构建查询条件
     */
    private void buildQueryConditions(MPJLambdaWrapper<Equipment> wrapper, Map<String, Object> params) {
        String code = (String) params.get("code");
        String address = (String) params.get("address");
        Integer isStatus = (Integer) params.get("isStatus");
        Integer status = (Integer) params.get("status");
        Integer storageStatus = (Integer) params.get("storageStatus");

        if (StringUtils.hasText(code)) {
            wrapper.like(Equipment::getCode, code);
        }
        if (StringUtils.hasText(address)) {
            wrapper.like(Equipment::getAddress, address);
        }
        if (isStatus != null) {
            wrapper.eq(Equipment::getIsStatus, isStatus);
        }
        if (status != null) {
            wrapper.eq(Equipment::getStatus, status);
        }
        if (storageStatus != null) {
            wrapper.eq(Equipment::getStorageStatus, storageStatus);
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class) // 添加rollbackFor确保所有异常都回滚
    public R insert(Map<String, Object> params) {
        System.out.println("添加设备管理");

        try {
            Equipment equipment = new Equipment();
            equipment.setCompanyId((Integer) params.get("companyId"));
            equipment.setSalesName((String) params.get("salesName").toString());
            equipment.setSalesPhone((String) params.get("salesPhone").toString());
            equipment.setEquipmentSn((String) params.get("equipmentSn").toString());
            equipment.setCode( params.get("code").toString());
            equipment.setName((String) params.get("name").toString());
            equipment.setPrice(BigDecimal.valueOf((Integer) params.get("price")));
            equipment.setVersionNumber(60);
            equipment.setThreshold(BigDecimal.valueOf((Integer) params.get("threshold")));
            equipment.setLongitude(params.get("longitude").toString());
            equipment.setLatitude(params.get("latitude").toString());
            equipment.setNowWeight(BigDecimal.valueOf(0.0));
            equipment.setTotalWeight(BigDecimal.valueOf(0.0));
            equipment.setStatus((Integer) params.get("status"));
            equipment.setStorageStatus((Integer) params.get("storageStatus"));
            equipment.setIsStatus(1);
            equipment.setAddress((String) params.get("address"));
            equipment.setRemarks((String) params.get("remarks"));

            System.out.println("添加的数据为：" + equipment);
            int row = equipmentDao.insert(equipment);

            // 如果设备插入失败，直接返回错误
            if (row <= 0) {
                throw new RuntimeException("设备信息插入失败"); // 抛出异常触发回滚
            }

            // 获取新插入设备的ID
            Integer equipmentId = equipment.getId();

            // 处理清理人员列表
            List<Integer> cleanList = (List<Integer>) params.get("cleanList");
            System.out.println("清理人员列表：" + cleanList);
            if (cleanList != null && !cleanList.isEmpty()) {
                for (Integer cleanId : cleanList) {
                    Equipment_clean equipmentClean = new Equipment_clean();
                    equipmentClean.setEquipmentId(equipmentId);
                    equipmentClean.setCleanId(cleanId);
                    System.out.println("添加清理人员关联信息：" + equipmentClean);
                    int cleanRow = equipment_cleanDao.insert(equipmentClean);

                    // 如果关联记录插入失败，抛出异常回滚
                    if (cleanRow <= 0) {
                        throw new RuntimeException("清理人员关联信息插入失败");
                    }
                }
                System.out.println("添加了 " + cleanList.size() + " 条清理人员关联记录");
            }

            return R.ok();

        } catch (Exception e) {
            // 记录错误日志
            System.err.println("插入设备信息失败: " + e.getMessage());
            // 异常会自动触发事务回滚
            throw new RuntimeException("设备信息保存失败", e); // 重新抛出异常确保回滚
        }
    }

    @Override
    public R getInstallList(Map<String, Object> params) {
        Page page = new Page();
        page.setCurrent((Integer) params.get("pageIndex"));
        page.setSize((Integer) params.get("pageSize"));
        MPJLambdaWrapper<Equipment_installation> wrapper = new MPJLambdaWrapper<>(Equipment_installation.class)
                .select(Equipment_installation::getId,
                        Equipment_installation::getEquipmentId,
                        Equipment_installation::getInstallTime,
                        Equipment_installation::getInstallerId
                        )
                .select(Equipment::getCode,
                        Equipment::getAddress,
                        Equipment::getCommunity)
                .select(CustomerVO::getRealname)
                .leftJoin(Equipment.class, Equipment::getId, Equipment_installation::getEquipmentId)
                .leftJoin(CustomerVO.class, CustomerVO::getId, Equipment_installation::getInstallerId)
                .orderByDesc(Equipment_installation::getInstallTime);
        String code = (String) params.get("code");
        String name = (String) params.get("name");
        String startTime = (String) params.get("startTime");
        String endTime = (String) params.get("endTime");
        if (StringUtils.hasText(code)) {
            wrapper.like(Equipment::getCode, code);
        }
        if (StringUtils.hasText(name)) {
            wrapper.like(CustomerVO::getRealname, name);
        }
        if (StringUtils.hasText(startTime)) {
            wrapper.ge(Equipment_installation::getInstallTime, startTime);
        }
        if (StringUtils.hasText(endTime)) {
            wrapper.le(Equipment_installation::getInstallTime, endTime);
        }

        Page<InstallReportVO> List = equipment_installDao.selectJoinPage(page, InstallReportVO.class, wrapper);
        Map<String, Object> map = new HashMap<>();
        map.put("totalSize", List.getTotal());
        map.put("list", List.getRecords());
        return R.ok(map);
    }


    @Override
    @Transactional
    public R update(Map<String, Object> params) {
        System.out.println("修改设备管理");

        // 获取设备ID
        Integer equipmentId = (Integer) params.get("id");
        if (equipmentId == null) {
            return R.er("设备ID不能为空");
        }

        // 查询设备是否存在
        Equipment existingEquipment = equipmentDao.selectById(equipmentId);
        if (existingEquipment == null) {
            return R.er("设备不存在");
        }

        // 更新设备基本信息
        Equipment equipment = new Equipment();
        equipment.setId(equipmentId);
        equipment.setCompanyId((Integer) params.get("companyId"));
        equipment.setSalesName( params.get("salesName").toString());
        equipment.setSalesPhone((String) params.get("salesPhone").toString());
        equipment.setEquipmentSn((String) params.get("equipmentSn").toString());
        equipment.setCode((String) params.get("code").toString());
        equipment.setName((String) params.get("name").toString());
        equipment.setPrice(BigDecimal.valueOf((Integer) params.get("threshold")));
        equipment.setVersionNumber((Integer) params.get("versionNumber"));
        equipment.setThreshold(BigDecimal.valueOf((Integer) params.get("threshold")));
        equipment.setLongitude(params.get("longitude").toString());
        equipment.setLatitude(params.get("latitude").toString());
        equipment.setStatus((Integer) params.get("status"));
        equipment.setStorageStatus((Integer) params.get("storageStatus"));

        equipment.setAddress( params.get("address").toString());
        equipment.setRemarks( params.get("remarks").toString());

        System.out.println("修改的设备数据为：" + equipment);
        int row = equipmentDao.updateById(equipment);

        if (row > 0) {
            // 处理清理人员列表的更新
            List<Integer> cleanList = (List<Integer>) params.get("cleanList");
            System.out.println("新的清理人员列表：" + cleanList);

            // 查询现有的清理人员关联
            List<Equipment_clean> existingRelations = equipment_cleanDao.selectByEquipmentId(equipmentId);
            List<Integer> existingCleanIds = existingRelations.stream()
                    .map(Equipment_clean::getCleanId)
                    .collect(Collectors.toList());

            // 简单判断：是否有变化
            boolean hasChanged = !isSameList(existingCleanIds, cleanList);

            if (hasChanged) {
                // 先删除原有的清理人员关联
                deleteCleanRelationsByEquipmentId(equipmentId);

                // 再添加新的清理人员关联
                if (cleanList != null && !cleanList.isEmpty()) {
                    for (Integer cleanId : cleanList) {
                        Equipment_clean equipmentClean = new Equipment_clean();
                        equipmentClean.setEquipmentId(equipmentId);
                        equipmentClean.setCleanId(cleanId);
                        equipment_cleanDao.insert(equipmentClean);
                    }
                }
            }

            return R.ok();
        } else {
            return R.er("设备更新失败");
        }
    }

    @Override
    public R getInfo(Integer id) {
        // 查询设备基本信息
        MPJLambdaWrapper<Equipment> wrapper = new MPJLambdaWrapper<>(Equipment.class)
                .selectAll(Equipment.class)
                .leftJoin(EquipmentHolder.class, EquipmentHolder::getEquipmentId, Equipment::getId)
                .select(CustomerVO::getRealname, CustomerVO::getPhone)
                .leftJoin(CustomerVO.class, CustomerVO::getId, EquipmentHolder::getCustomerId)
                .selectAs(OrganizationVO::getId,"companyId")
                .leftJoin(OrganizationVO.class, OrganizationVO::getId, Equipment::getCompanyId)
                .eq(Equipment::getId, id)
                .eq(Equipment::getIsDeleted, 0);

        ExceptionManagerVO vo = equipmentDao.selectJoinOne(ExceptionManagerVO.class, wrapper);

        // 查询清理人员关联信息
        List<Equipment_clean> cleanRelations = equipment_cleanDao.selectByEquipmentId(id);
        List<Long> cleanList = cleanRelations.stream()
                .map(relation -> Long.valueOf(relation.getCleanId()))
                .collect(Collectors.toList());
        vo.setCleanList(cleanList);

        Map<String, Object> map = new HashMap<>();
        map.put("list", vo);

        return R.ok(map);
    }


    /**
     * 简单判断两个列表是否相同
     */
    private boolean isSameList(List<Integer> list1, List<Integer> list2) {
        if (list1 == null && list2 == null) return true;
        if (list1 == null || list2 == null) return false;
        if (list1.size() != list2.size()) return false;

        // 简单比较：排序后转为字符串比较
        List<Integer> sorted1 = new ArrayList<>(list1);
        List<Integer> sorted2 = new ArrayList<>(list2);
        Collections.sort(sorted1);
        Collections.sort(sorted2);

        return sorted1.equals(sorted2);
    }

    /**
     * 根据设备ID删除清理人员关联关系
     */
    private void deleteCleanRelationsByEquipmentId(Integer equipmentId) {
        int deletedCount = equipment_cleanDao.deleteByEquipmentId(equipmentId);
        System.out.println("删除的清理人员关联关系数量：" + deletedCount);
    }

    //TODO 设备日志表
    @Override
    public R getLog(Map<String, Object> params) {
        System.out.println("获取设备日志");
        Page page = new Page<>();
        page.setCurrent((Integer) params.get("pageIndex"));
        page.setSize((Integer) params.get("pageSize"));
        MPJLambdaWrapper<Equipment_log> wrapper = new MPJLambdaWrapper<>(Equipment_log.class)
                .selectAll()
                .select(Equipment::getCode, Equipment::getName)
                .leftJoin(Equipment.class, Equipment::getId, Equipment_log::getEquipmentId);
        String code = (String) params.get("code");
        String name = (String) params.get("name");
        String operation = (String) params.get("operation");
        if (StringUtils.hasText(code)) {
            wrapper.like(Equipment::getCode, code);
        }
        if (StringUtils.hasText(name)) {
            wrapper.like(Equipment::getName, name);
        }
        if (StringUtils.hasText(operation)){
            wrapper.like(Equipment_log::getOperation, operation);
        }
        Page<Equipment_log> List = equipment_logDao.selectJoinPage(page, Equipment_logVO.class, wrapper);
        Map<String, Object> map = new HashMap<>();
        map.put("totalSize", List.getTotal());
        map.put("list", List.getRecords());
        return R.ok(map);
    }

    /**
     * 每五分钟记录设备日志的定时任务
     */
    @Scheduled(fixedDelay = 300000) // 300000毫秒 = 5分钟
    @Transactional
    @Override
    public void recordEquipmentLogPeriodically() {
        try {
            String currentTime = getCurrentDateTime();
            log.info("开始执行设备日志记录，当前时间: {}", currentTime);

            // 获取所有活跃设备
            List<Equipment> activeEquipments = getActiveEquipments();

            if (activeEquipments.isEmpty()) {
                log.info("未找到活跃设备，跳过本次记录");
                return;
            }

            int recordedCount = 0;

            // 为每个活跃设备记录日志
            for (Equipment equipment : activeEquipments) {
                boolean success = recordSingleEquipmentLog(equipment);
                if (success) {
                    recordedCount++;
                }
            }

            log.info("设备日志记录完成，成功记录 {} 条日志，时间: {}", recordedCount, currentTime);

        } catch (Exception e) {
            log.error("记录设备日志时发生错误: {}", e.getMessage());
            e.printStackTrace();
        }
    }

    @Override
    public R getCompanyList(Map<String, Object> params) {
        System.out.println("获取公司列表");
        Page page = new Page();
        page.setCurrent((Integer) params.get("pageIndex"));
        page.setSize((Integer) params.get("pageSize"));
        MPJLambdaWrapper<OrganizationVO> wrapper = new MPJLambdaWrapper<>(OrganizationVO.class)
                .select(OrganizationVO::getId, OrganizationVO::getName);
        Page<OrganizationVO> List = organizationDdao.selectJoinPage(page, OrganizationVO.class, wrapper);
        Map<String, Object> map = new HashMap<>();
        map.put("totalSize", List.getTotal());
        map.put("list", List.getRecords());
        return R.ok(map);
    }

    /**
     * 获取当前时间字符串
     */
    private String getCurrentDateTime() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 获取所有活跃设备
     */
    private List<Equipment> getActiveEquipments() {
        MPJLambdaWrapper<Equipment> queryWrapper = new MPJLambdaWrapper<>(Equipment.class);
        queryWrapper.eq("is_status", 1); // 状态为1表示正常运行的设备
        return equipmentDao.selectList(queryWrapper);
    }

    /**
     * 记录单个设备的日志
     */
    private boolean recordSingleEquipmentLog(Equipment equipment) {
        try {
            Equipment_log equipmentLog = new Equipment_log();
            equipmentLog.setEquipmentId(equipment.getId());
            equipmentLog.setOperation("定时监测");

            // 构建请求数据
            String requestData = "{"
                    +"sn:'"+equipment.getEquipmentSn()+"',"
                    +"code:'"+equipment.getCode()+"',"
                    +"name:'"+equipment.getName()+"',"
                    +"status:'"+equipment.getStatus()+"',"
                    +"version:'"+equipment.getVersionNumber()+"',"
                    +"now_weight:'"+equipment.getNowWeight()+"',"
                    +"storageStatus:'"+equipment.getStorageStatus()+"',"
                    +"isStatus:'"+equipment.getIsStatus()+"}" ;
            equipmentLog.setRequest_data(requestData);
            // 插入数据库
            int result = equipment_logDao.insert(equipmentLog);

            return result > 0;

        } catch (Exception e) {
            log.error("记录设备 {} 的日志时发生错误: {}", equipment.getCode(), e.getMessage());
            return false;
        }
    }



}
